package stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * Description: stream示例demo
 *
 * @author code-worker
 * @date 2021/10/10 16:24
 */
public class StreamDemo {

    /**
     * task: 筛选
     * @author code-worker
     * @date 2021/10/10 16:28
     */
    static void filterDemo(){
        //简单筛选
        List<Dish> vegetarianMenu = Dish.initMenu()
                .stream()
                .filter(Dish::isVegetarian)
                .collect(Collectors.toList());
        System.out.println("素食菜单==>"+vegetarianMenu);

        //过滤重复
        List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 4, 3, 3, 2, 1));
        System.out.println("\n带重复的数据："+numbers);
        System.out.println("过滤重复后的数据："+numbers.stream().distinct().collect(Collectors.toList()));

        //获取指定数量数据
        System.out.println("只获取前三个数据："+numbers.stream().limit(3).collect(Collectors.toList()));
        System.out.println("跳过前两个数据："+numbers.stream().skip(2).collect(Collectors.toList()));
    }

    /**
     * task: 映射
     * @author code-worker
     * @date 2021/10/10 16:36
     */
    static void mapDemo(){
        List<String> dishName = Dish.initMenu()
                .stream()
                .map(Dish::getName)
                .collect(Collectors.toList());
        System.out.println(dishName);

        List<Integer> dishNameLen = Dish.initMenu()
                .stream()
                .map(Dish::getName)
                .map(String::length)
                .collect(Collectors.toList());
        System.out.println(dishNameLen);

        //数据扁平化
        String[] strArray = new String[2];
        strArray[0] = "hello";
        strArray[1] = "world";
        List<String> list = new ArrayList<String>(Arrays.asList(strArray));
//        System.out.println(list.stream().map(word -> word.split("")).collect(Collectors.toList()));
        System.out.println(list.stream()
                .flatMap(word -> Arrays.stream(word.split("")))
                .collect(Collectors.toList()));
    }

    /**
     * task: 匹配或查找
     * @author code-worker
     * @date 2021/10/10 21:04
     */
    static void matchAndFind(){
        //anyMatch():终端操作，检查谓词是否至少匹配一个元素
        if(Dish.initMenu().stream().anyMatch(Dish::isVegetarian)){
            System.out.println("The menu is (somewhat) vegetarian friendly!");
        }
        //allMatch():检查谓词是否匹配所有元素
        if(Dish.initMenu().stream().allMatch(d -> d.getCalories() < 1000)){
            System.out.println("The menu is healthy");
        }
        //noneMatch():检查谓词是否不匹配任何元素
        if (Dish.initMenu().stream().noneMatch(d -> d.getCalories() >= 1000)) {
            System.out.println("The menu is healthy");
        }

        //findAny():返回当前流中的任意元素，可以与其他流操作结合使用
        Optional<Dish> dish = Dish.initMenu().stream()
                .filter(Dish::isVegetarian)
                .findAny();
        dish.ifPresent(System.out::println);
        //findFirst():查找流的第一个元素
        Optional<Dish> firstVegetarianDish = Dish.initMenu().stream().filter(Dish::isVegetarian).findFirst();
        firstVegetarianDish.ifPresent(System.out::println);
    }

    /**
     * task: 归约
     * @author code-worker
     * @date 2021/10/11 12:45
     */
    static void reduceDemo(){
        List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
        //求和
        System.out.println(numbers.stream().reduce(0, Integer::sum));
        //求积
        System.out.println(numbers.stream().reduce(1, (a, b) -> a * b));
        //无初始值
        Optional<Integer> sum = numbers.stream().reduce(Integer::sum);
        sum.ifPresent(System.out::println);
        //最大值(不存在返回0)
        System.out.println(numbers.stream().reduce(Integer::max).orElseGet(()-> 0));
    }

    /**
     * task: 数值流
     * @author code-worker
     * @date 2021/10/11 12:56
     */
    static void baseTypeDemo(){
        //映射到数值流
        int calories = Dish.initMenu()
                .stream()
                .mapToInt(Dish::getCalories)
                .sum();
        System.out.println(calories);

        //转换回对象流
        IntStream intStream = Dish.initMenu().stream().mapToInt(Dish::getCalories);
        Stream<Integer> stream = intStream.boxed();
        stream.forEach(data -> System.out.print(data + " "));

        //默认值OptionalInt
        OptionalInt maxCalories = Dish.initMenu()
                .stream()
                .mapToInt(Dish::getCalories)
                .max();
        System.out.println();
        maxCalories.ifPresent(System.out::println);

        //数值范围
        IntStream evenNumbers = IntStream
                .range(1, 100)
                .filter(n -> n % 2 == 0);
        evenNumbers.forEach(data -> System.out.print(data + " "));
    }

    public static void main(String[] args) {
        baseTypeDemo();
    }

}
